#include <iostream>
#include <pthread.h>
#include <vector>
#include <unistd.h>
#include <string>

/////////////////////////////////////////////////////////////////////////////////////////////////////
// 线程基础示例
void *rotine01(void *args)
{
    std::string name = static_cast<const char *>(args);
    pthread_t tid = pthread_self();
    int cnt = 5;
    while (cnt--)
    {
        std::cout << "这是新线程，name: " << name << "，线程id为：" << tid << std::endl;
        sleep(1);
    }

    return (void *)10;
}

void test01()
{
    pthread_t tid = 0;
    int n = pthread_create(&tid, nullptr, rotine01, (void *)"threadd-1");
    int cnt = 5;
    while (cnt--)
    {
        std::cout << "这是主线程，name: main-thread" << "，线程id为：" << pthread_self() << std::endl;
        sleep(1);
    }

    void *ret = nullptr;
    pthread_join(tid, &ret);
    std::cout << "进程退出，退出码为: " << (long long)ret << std::endl;
}

//////////////////////////////////////////////////////////////////////////////////////////////////////
// 线程传参自定义类型
/* 如果需要只终⽌某个线程⽽不终⽌整个进程,可以有三种⽅法:
1. 从线程函数return。这种⽅法对主线程不适⽤,从main函数return相当于调⽤exit。
2. 线程可以调⽤pthread_ exit终⽌⾃⼰。
3. ⼀个线程可以调⽤pthread_ cancel终⽌同⼀进程中的另⼀个线程。 */
class Task
{
public:
    Task(int a, int b) : _a(a), _b(b)
    {
    }

    int Excute()
    {
        return _a + _b;
    }

    ~Task()
    {
    }

private:
    int _a;
    int _b;
};

class Result
{
public:
    Result(int res) : _res(res)
    {
    }

    int GetResult()
    {
        return _res;
    }

    ~Result()
    {
    }

private:
    int _res;
};

void *rotine02(void *args)
{
    Task *t = static_cast<Task *>(args);
    Result *res = new Result(t->Excute());
    std::cout << "我是新线程，我在执行task任务" << std::endl;
    sleep(1);
    int cnt = 5;
    while (cnt--)
    {
        std::cout << "......";
        fflush(stdout);
        sleep(1);
    }
    std::cout << std::endl;
    std::cout << "success!!!" << std::endl;
    fflush(stdout);

    pthread_exit(res);
    std::cout << "用pthread_exit退出线程后，此行是看不到的" << std::endl;
    // pthread_exit()是线程主动退出，它可以顺带返回我们要返回的信息

    // return res;
}

void test02()
{
    pthread_t tid = 0;

    Task *t = new Task(1, 2);

    int n = pthread_create(&tid, nullptr, rotine02, (void *)t);
    std::cout << "向线程发送任务" << std::endl;
    sleep(3);

    // 取消操作
    // pthread_cancel(tid);
    // std::cout << "线程被取消" << std::endl;

    void *ret = nullptr;
    pthread_join(tid, &ret);
    std::cout << "接收线程结果成功，result: " << ((Result *)ret)->GetResult() << std::endl;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////
// 分离线程
void *rotine03(void *args)
{
    pthread_detach(pthread_self());
    std::string name = static_cast<const char *>(args);
    pthread_t tid = pthread_self();
    int cnt = 5;
    while (cnt--)
    {
        std::cout << "这是新线程，name: " << name << "，线程id为：" << tid << std::endl;
        sleep(1);
    }
    return nullptr;
}

void test03()
{
    pthread_t tid = 0;
    int n = pthread_create(&tid, nullptr, rotine03, (void *)"threadd-1");
    int cnt = 5;
    while (cnt--)
    {
        std::cout << "这是主线程，name: main-thread" << "，线程id为：" << pthread_self() << std::endl;
        sleep(1);
    }

    // 分离的线程不能再被回收，该线程推出后会自动释放资源。
    //  void* ret = nullptr;
    //  pthread_join(tid, &ret);
    //  std::cout << "进程退出，退出码为: " << (long long)ret << std::endl;
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////
// 多线程
void *rotine04(void *args)
{
    std::string name = static_cast<const char *>(args);
    int* n = new int(std::stoi(name.substr(name.size() - 2)));
    pthread_t tid = pthread_self();
    int cnt = 5;
    while (cnt--)
    {
        std::cout << "这是新线程，name: " << name << "，线程id为：" << tid << std::endl;
        sleep(1);
    }

    return (void*)n;
}

void test04()
{

    std::vector<pthread_t> tids;

    for (int i = 0; i <= 5; i++)
    {
        sleep(1);
        pthread_t tid = 0;
        char *name = new char[64];
        snprintf(name, 64, "thread-%d", i);
        int n = pthread_create(&tid, nullptr, rotine01, (void *)name);
        if(n == 0)
            tids.push_back(tid);
        else
            continue;

    }

    std::cout << "这是主线程，name: main-thread " << "，线程id为：" << pthread_self() << std::endl;
        

    for (int j = 0; j <= 5; j++)
    {
        void *ret = nullptr;
        pthread_join(tids[j], &ret);
        std::cout << "线程退出，退出码为: " << (long long)ret << std::endl;
    }
}

int main()
{
    // test01();
    //test02();
    ///test03();
    test04();
    return 0;
}